﻿using System;

using zijian666.Converts.Core;

namespace zijian666.Converts.Abstractions;

/// <summary>
/// 处理指定类型的转换接口
/// </summary>
/// <typeparam name="TOutput"></typeparam>
/// <typeparam name="TInput"></typeparam>
public interface IFrom<TInput, TOutput>
{
    /// <summary>
    /// 从 <typeparamref name="TInput"/> 转为 <typeparamref name="TOutput"/>
    /// </summary>
    /// <param name="context">转换上下文</param>
    /// <param name="input">输入值</param>
    /// <returns></returns>
    ConvertResult<TOutput> From(IConvertContext context, TInput input);
}

/// <summary>
/// 扩展方法
/// </summary>
internal static class IFromExtensions
{
    /// <summary>
    /// 尝试调用 <seealso cref="IFrom{TInput, TOutput}.From(IConvertContext, TInput)"/> 并处理异常
    /// </summary>
    /// <typeparam name="TInput">转换前类型</typeparam>
    /// <typeparam name="TOutput">转换后类型</typeparam>
    /// <param name="from"><seealso cref="IFrom{TInput, TOutput}"/>接口实现</param>
    /// <param name="context">转换上下文</param>
    /// <param name="input">输入值</param>
    /// <param name="ecollector">异常收集器</param>
    /// <returns></returns>
    public static ConvertResult<TOutput> TryFrom<TInput, TOutput>(this IFrom<TInput, TOutput>? from, IConvertContext context, TInput input, ref ExceptionCollector? ecollector)
    {
        if (from is null)
        {
            return ConvertResult<TOutput>.FAIL;
        }
        try
        {
            var result = from.From(context, input);
            if (result.Success)
            {
                return result;
            }
            ExceptionCollector.Collect(ref ecollector, result.Exception);
        }
        catch (Exception e)
        {
            ExceptionCollector.Collect(ref ecollector, e);
        }
        return ConvertResult<TOutput>.FAIL;
    }
}